package org.design.hotdevelop.aop;

import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.design.hotdevelop.annotaion.HotSwap;
import org.design.hotdevelop.register.LoadBeanService;
import org.design.hotdevelop.service.SwitchService;
import org.springframework.beans.BeansException;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;


/**
 * @author freedom
 * @description
 * @date 2024/3/9 18:40
 */
@Slf4j
@Aspect
@Component
public class HotSwapAspect {


    @Around("@within(org.design.hotdevelop.annotaion.HotSwap)")
    public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取目标对象
        Object target = joinPoint.getTarget();
        // 获取目标对象的类
        Class<?> targetClass = target.getClass();
        // 检查类是否带有 @HotSwap 注解
        if (targetClass.isAnnotationPresent(HotSwap.class)) {
            // 获取注解实例
            HotSwap hotSwapAnnotation = targetClass.getAnnotation(HotSwap.class);
            String value = hotSwapAnnotation.value();
            log.info("Class is annotated with @HotSwap, value:{}", value);
            Object bean = null;
            try {
                bean = SpringUtil.getBean(value + "_V_"+ LoadBeanService.ATOMIC_INTEGER.get());
                HotSwap hotSwapAnnotation_V = bean.getClass().getAnnotation(HotSwap.class);
                String value_V = hotSwapAnnotation_V.value();
                int i1 = value_V.indexOf("_V_");
                if(i1>-1){
                    value_V = value_V.substring(0,i1);
                    Map<String,String> switchMap = SwitchService.SWITCH_MAP;
                    String s = switchMap.get(value_V);
                    if("0".equals(s)){
                        return joinPoint.proceed();
                    }
                }
                log.info("newBean:{}", bean);
                if (bean != null) {
                    // 获取被拦截的方法名
                    String methodName = joinPoint.getSignature().getName();
                    // 获取方法参数
                    Object[] args = joinPoint.getArgs();
                    // 获取方法参数的类型
                    Class<?>[] argTypes = new Class<?>[args.length];
                    for (int i = 0; i < args.length; i++) {
                        argTypes[i] = args[i].getClass();
                    }
                    log.info("Method name: {}, Argument types: {}", methodName, Arrays.toString(argTypes));

                    // 使用反射调用新的 MyService 实现的方法
                    Method method = bean.getClass().getMethod(methodName, argTypes);
                    return method.invoke(bean, args);
                }
            } catch (BeansException e) {
                log.warn("Bean does not exist: {}", e.getMessage());
            } catch (NoSuchMethodException e) {
                log.warn("Method not found: {}", e.getMessage());
            } catch (Exception e) {
                log.error("Error invoking method: {}", e.getMessage(), e);
            }
        }
        // 继续执行原方法
        return joinPoint.proceed();
    }

}